package connectionpool;

import org.apache.log4j.Logger;
import service.DataSource;

import java.sql.Connection;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class ConnectionPoolSemaphore implements ConnectionPool {
    private final Set<Connection> connectionSet = new HashSet<>();
    private final Queue<Connection> activeConnectionQueue = new ConcurrentLinkedQueue<>();
    private final Semaphore semaphore;

    private static final Logger logger = Logger.getLogger(ConnectionPoolSemaphore.class);

    public ConnectionPoolSemaphore(DataSource dataSource, int connectionCount) {
        for (int i = 0; i < connectionCount; i++) {
            Connection connection = dataSource.getConnection();
            connectionSet.add(connection);
            activeConnectionQueue.add(connection);
        }
        semaphore = new Semaphore(connectionCount);
    }

    @Override
    public Connection getConnection() {
        return getConnection(0);
    }

    @Override
    public Connection getConnection(int timeout) {
        try {
            if (timeout > 0) {
                semaphore.tryAcquire(timeout, TimeUnit.SECONDS);
            } else {
                semaphore.acquire();
            }
            return activeConnectionQueue.poll();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("Interrupted while trying to get connection, returning null");
            return null;
        }
    }

    @Override
    public void release(Connection connection) {
        if (connectionSet.contains(connection)) {
            synchronized (activeConnectionQueue) {
                if (!activeConnectionQueue.contains(connection)) {
                    activeConnectionQueue.add(connection);
                    semaphore.release();
                }
            }
        }
    }
}
